//
//  MultipleLayersParentNode.cpp
//  NMGame-mobile
//
//  Created by nieming on 2018/8/20.
//

#include "MultipleLayersParentNode.hpp"
#include "MultipleLayersNode.hpp"
USING_NS_CC;

MultipleLayersParentNode * MultipleLayersParentNode::create(int layersNum){
    MultipleLayersParentNode * ret = new (std::nothrow) MultipleLayersParentNode(layersNum);
    if (ret && ret->init())
    {
        ret->autorelease();
    }
    else
    {
        CC_SAFE_DELETE(ret);
    }
    return ret;
}

MultipleLayersParentNode::MultipleLayersParentNode(int layersNum){
    _layersNum = layersNum;
}

MultipleLayersParentNode::~MultipleLayersParentNode(){
    
}

void MultipleLayersParentNode::visit(Renderer* renderer, const Mat4 &parentTransform, uint32_t parentFlags)
{
    //忽略 protectedNode
    
    // quick return if not visible. children won't be drawn.
    if (!_visible)
    {
        return;
    }
    
    uint32_t flags = processParentFlags(parentTransform, parentFlags);
    
    // IMPORTANT:
    // To ease the migration to v3.0, we still support the Mat4 stack,
    // but it is deprecated and your code should not rely on it
    _director->pushMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    _director->loadMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW, _modelViewTransform);
    
    bool visibleByCamera = isVisitableByVisitingCamera();
    
    int i = 0;
    
    if(!_children.empty())
    {
        sortAllChildren();
        // draw children zOrder < 0
        for(auto size = _children.size(); i < size; ++i)
        {
            auto node = _children.at(i);
            if (node && node->getLocalZOrder() < 0){
                // local order <0 走正常渲染流程
                node->visit(renderer, _modelViewTransform, flags);
            }

            else
                break;
        }
        // self draw
        if (visibleByCamera)
            this->draw(renderer, _modelViewTransform, flags);
        
        for (int k = 0; k <= _layersNum; k++){
            for(auto it=_children.cbegin()+i, itCend = _children.cend(); it != itCend; ++it){
                // 这里没有使用 dynamic_cast<typeMultipleLayersNode *> 没做类型安全检查 主要出于执行效率的考虑
                MultipleLayersNode * child = static_cast<MultipleLayersNode *>(*it);
                child->visit(renderer, _modelViewTransform, flags, k, k == _layersNum);
            }
        }
    }
    else if (visibleByCamera)
    {
        this->draw(renderer, _modelViewTransform, flags);
    }
    
    _director->popMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW);
    
}

void MultipleLayersParentNode::copyProp(ui::Widget* model){
    
    copyProperties(model);
}

MultipleLayersParentNode * MultipleLayersParentNode::createCloneInstance(){
    return MultipleLayersParentNode::create(_layersNum);
}

void MultipleLayersParentNode::addChild(Node *child, int localZOrder, int tag)
{
    MultipleLayersNode * lNode = dynamic_cast<MultipleLayersNode *>(child);
    CCASSERT(lNode != nullptr, "MultipleLayersParentNode child must be MultipleLayersNode type");
    if (lNode) {
         Node::addChild(child, localZOrder, tag);
    }
   
}

void MultipleLayersParentNode::addChild(Node* child, int localZOrder, const std::string &name)
{
    MultipleLayersNode * lNode = dynamic_cast<MultipleLayersNode *>(child);
    CCASSERT(lNode != nullptr, "MultipleLayersParentNode child must be MultipleLayersNode type");
    if (lNode) {
        Node::addChild(child, localZOrder, name);
    }
}
void MultipleLayersParentNode::addChild(Node *child, int zOrder)
{
    this->addChild(child, zOrder, child->getName());
}

void MultipleLayersParentNode::addChild(Node *child)
{
    CCASSERT( child != nullptr, "Argument must be non-nil");
    this->addChild(child, child->getLocalZOrder(), child->getName());
}
